package com.taysear.parcel;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;

import com.taysear.parcel.domain.Account;
import com.taysear.parcel.domain.AccountStatus;
import com.taysear.parcel.domain.Bus;
import com.taysear.parcel.domain.Country;
import com.taysear.parcel.domain.Currency;
import com.taysear.parcel.domain.Customer;
import com.taysear.parcel.domain.Employee;
import com.taysear.parcel.domain.EmployeeStatus;
import com.taysear.parcel.domain.EmployeeType;
import com.taysear.parcel.domain.Gender;
import com.taysear.parcel.domain.ParcelAction;
import com.taysear.parcel.domain.ParcelStatus;
import com.taysear.parcel.domain.ParcelType;
import com.taysear.parcel.domain.PaymentMode;
import com.taysear.parcel.domain.Route;
import com.taysear.parcel.domain.RouteDetail;
import com.taysear.parcel.domain.RouteStatus;
import com.taysear.parcel.domain.Station;
import com.taysear.parcel.domain.StationStatus;
import com.taysear.parcel.domain.Substation;
import com.taysear.parcel.domain.User;
import com.taysear.parcel.fieldfactory.AccountFieldFactory;
import com.taysear.parcel.fieldfactory.BusFieldFactory;
import com.taysear.parcel.fieldfactory.CountryFieldFactory;
import com.taysear.parcel.fieldfactory.CurrencyFieldFactory;
import com.taysear.parcel.fieldfactory.CustomerFieldFactory;
import com.taysear.parcel.fieldfactory.EmployeeFieldFactory;
import com.taysear.parcel.fieldfactory.EmployeeStatusFieldFactory;
import com.taysear.parcel.fieldfactory.EmployeeTypeFieldFactory;
import com.taysear.parcel.fieldfactory.ParcelActionFieldFactory;
import com.taysear.parcel.fieldfactory.ParcelStatusFieldFactory;
import com.taysear.parcel.fieldfactory.ParcelTypeFieldFactory;
import com.taysear.parcel.fieldfactory.PaymentModeFieldFactory;
import com.taysear.parcel.fieldfactory.RouteFieldFactory;
import com.taysear.parcel.fieldfactory.StationFieldFactory;
import com.taysear.parcel.fieldfactory.StationStatusFieldFactory;
import com.taysear.parcel.fieldfactory.SubstationFieldFactory;
import com.taysear.parcel.fieldfactory.UserFieldFactory;
import com.taysear.parcel.util.Constants;
import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.addon.jpacontainer.JPAContainerFactory;
import com.vaadin.addon.jpacontainer.fieldfactory.FieldFactory;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.util.filter.And;
import com.vaadin.data.util.filter.Compare.Equal;
import com.vaadin.data.util.filter.Not;
import com.vaadin.event.Action;
import com.vaadin.event.ShortcutAction;
import com.vaadin.event.Action.Handler;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.ui.AbsoluteLayout;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Form;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Panel;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.Reindeer;
import com.vaadin.ui.themes.Runo;

/**
 * This is a rudimentary general purpose CRUD view to list and edit JPA entities
 * with JPAContainer. Lists all entities in a table and puts the selected row
 * into a buffered form below it. Form uses {@link FieldFactory} to support most
 * common relation types.
 */
public class BasicCrudView<T> extends AbsoluteLayout implements
		Property.ValueChangeListener, Handler, ClickListener {

	private ParcelApplication app;
	private JPAContainer<T> container;
	private Table table;
	private Form form;
	private FieldFactory fieldFactory;
	private Class<T> entityClass;
	private Button commit;
	private Button discard;
	private Object[] formAddPropertyIds;
	private Object[] formEditPropertyIds;
	private Button addButton;
	private Button editButton;
	private Button permissionButton;
	private Button routeDetailButton;
	private Panel panel;
	private final String persistenceUnit;
	private int formType = 0;
	private int formTypeCreate = 1;
	private int formTypeEdit = 2;
	private Subject currentUser;

	public BasicCrudView(ParcelApplication app, Class<T> entityClass, final String persistenceUnit, FieldFactory fieldFactory) {
		this.app = app;
		this.entityClass = entityClass;
		this.persistenceUnit = persistenceUnit;
		this.currentUser = SecurityUtils.getSubject();
		
		setSizeFull();
		initContainer();
		if(fieldFactory != null)
			this.fieldFactory = fieldFactory;
		else
			initFieldFactory();
		buildView();
	}

	protected void initFieldFactory() {
		fieldFactory = new FieldFactory();
	}

	protected FieldFactory getFieldFactory() {
		return fieldFactory;
	}

	protected Table getTable() {
		return table;
	}

	protected Form getForm() {
		return form;
	}

	public void setVisibleTableProperties(Object... tablePropertyIds) {
		table.setVisibleColumns(tablePropertyIds);
	}

	public void setVisibleAddFormProperties(Object... formPropertyIds) {
		this.formAddPropertyIds = formPropertyIds;
		form.setVisibleItemProperties(formPropertyIds);
	}
	
	public void setVisibleEditFormProperties(Object... formPropertyIds) {
		this.formEditPropertyIds = formPropertyIds;
	}

	protected void buildView() {
		setSizeFull();
		panel = new Panel(getCaption());
		panel.setSizeFull();
		addComponent(panel);

		VerticalLayout verticalLayout = new VerticalLayout();
		verticalLayout.setSizeFull();

		table.setSizeFull();
		table.addStyleName(Runo.TABLE_SMALL);
		table.setSelectable(true);
		table.addListener(this);
		table.setImmediate(true);
		table.addActionHandler(this);
		verticalLayout.addComponent(table);
		
		permissionButton = new Button("Permissions", this);
		permissionButton.setStyleName(Reindeer.BUTTON_SMALL);
		permissionButton.setVisible(false);
		addComponent(permissionButton, "top:0;right:135px;");
		
		routeDetailButton = new Button("Route details", this);
		routeDetailButton.setStyleName(Reindeer.BUTTON_SMALL);
		routeDetailButton.setVisible(false);
		addComponent(routeDetailButton, "top:0;right:135px;");

		addButton = new Button("Add", this);
		addButton.setDescription("Add new " + getEntityClass().getSimpleName());
		addButton.setStyleName(Reindeer.BUTTON_SMALL);
		addComponent(addButton, "top:0;right:70px;");

		editButton = new Button("Edit", this);
		editButton.setDescription("Edit selected " + getEntityClass().getSimpleName());
		editButton.setStyleName(Reindeer.BUTTON_SMALL);
		editButton.setEnabled(false);
		addComponent(editButton, "top:0;right:5px;");

		form = new Form();
		form.setVisible(false);
		form.setWriteThrough(false);
		form.setCaption(getEntityClass().getSimpleName());
		form.setFormFieldFactory(fieldFactory);
		commit = new Button("Save", new Button.ClickListener() {
			@Override
			public void buttonClick(ClickEvent event) {
				if(form.isValid()){
					if(entityClass == User.class){
						if(formType == formTypeCreate)
							saveUser();
						else
							editUser();
					} else if(entityClass == EmployeeType.class){
						if(formType == formTypeCreate)
							saveEmployeeType();
						else
							editEmployeeType();
					} else if(entityClass == EmployeeStatus.class){
						if(formType == formTypeCreate)
							saveEmployeeStatus();
						else
							editEmployeeStatus();
					} else if(entityClass == ParcelAction.class){
						if(formType == formTypeCreate)
							saveParcelAction();
						else
							editParcelAction();
					} else if(entityClass == ParcelStatus.class){
						if(formType == formTypeCreate)
							saveParcelStatus();
						else
							editParcelStatus();
					} else if(entityClass == ParcelType.class){
						if(formType == formTypeCreate)
							saveParcelType();
						else
							editParcelType();
					} else if(entityClass == PaymentMode.class){
						if(formType == formTypeCreate)
							savePaymentMode();
						else
							editPaymentMode();
					} else if(entityClass == StationStatus.class){
						if(formType == formTypeCreate)
							saveStationStatus();
						else
							editStationStatus();
					} else if(entityClass == Station.class){
						if(formType == formTypeCreate)
							saveStation();
						else
							editStation();
					} else if(entityClass == Substation.class){
						if(formType == formTypeCreate) {
							String code = form.getField("code").getValue().toString();
							String name = form.getField("name").getValue().toString();
							Integer stationId = (Integer) form.getField("station").getValue();
							Long statusId = (Long) form.getField("status").getValue();
							saveSubstation(code, name, stationId, statusId);
						}
						else
							editSubstation();
					} else if(entityClass == Employee.class){
						if(formType == formTypeCreate)
							saveEmployee();
						else
							editEmployee();
					} else if(entityClass == Bus.class){
						if(formType == formTypeCreate)
							saveBus();
						else
							editBus();
					} else if(entityClass == Country.class){
						if(formType == formTypeCreate)
							saveCountry();
						else
							editCountry();
					} else if(entityClass == Currency.class){
						if(formType == formTypeCreate)
							saveCurrency();
						else
							editCurrency();
					} else if(entityClass == Customer.class){
						if(formType == formTypeCreate)
							saveCustomer();
						else
							editCustomer();
					} else if(entityClass == Account.class){
						if(formType == formTypeCreate)
							saveAccount();
						else
							editAccount();
					}else if(entityClass == Route.class){
						if(formType == formTypeCreate)
							saveRoute();
						else
							editRoute();
					}
				}
			}
		});
		commit.setStyleName(Reindeer.BUTTON_SMALL);

		discard = new Button("Cancel", new Button.ClickListener() {
			@Override
			public void buttonClick(ClickEvent event) {
				form.discard();
			}
		});
		discard.setStyleName(Reindeer.BUTTON_SMALL);
		
		Button close = new Button("Close", new Button.ClickListener() {
			@Override
			public void buttonClick(ClickEvent event) {
				Window window = (Window) event.getButton().getParent().getParent().getParent().getParent();
				window.getParent().removeWindow(window);
			}
		});
		close.setStyleName(Reindeer.BUTTON_SMALL);
		
		form.getFooter().addComponent(commit);
		form.getFooter().addComponent(discard);
		form.getFooter().addComponent(close);
		form.getLayout().setMargin(true);
		form.getFooter().setMargin(false, true, false, true);
		((HorizontalLayout) form.getFooter()).setSpacing(true);

		panel.setContent(verticalLayout);

		// register action handler (enter and ctrl-n)
		panel.addActionHandler(this);
	}

	public Class<T> getEntityClass() {
		return entityClass;
	}

	protected void initContainer() {
		container = JPAContainerFactory.make(getEntityClass(), persistenceUnit);
		if(entityClass == Employee.class){
			Equal sid = new Equal("station.stationId", app.getUser().getEmployee().getStation().getStationId());
			Equal subid = new Equal("substation.substationId", app.getUser().getEmployee().getSubstation().getSubstationId());
			Boolean allEmp = currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_ALL_EMPLOYEE);
			Boolean stEmp = currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_STATION_EMPLOYEE);
			Boolean subEmp = currentUser.isPermitted(PermissionsConstants.PERMISSION_SYSTEM_SETTINGS_SUBSTATION_EMPLOYEE);
			if(allEmp)
				container.addContainerFilter(null);
			else if(stEmp)
				container.addContainerFilter(sid);
			else if(subEmp)
				container.addContainerFilter(subid);
			else
				container.addContainerFilter(new Equal("station.stationId", 0));
		} else if(entityClass == User.class){
			Not notRoot = new Not(new Equal("employee.employeeType.employeeTypeId", 99));
			Equal sid = new Equal("employee.station.stationId", app.getUser().getEmployee().getStation().getStationId());
			Equal subid = new Equal("employee.substation.substationId", app.getUser().getEmployee().getSubstation().getSubstationId());
			Boolean allUsers = currentUser.isPermitted(PermissionsConstants.PERMISSION_USER_MANAGEMENT_ALL_USERS);
			Boolean stUsers = currentUser.isPermitted(PermissionsConstants.PERMISSION_USER_MANAGEMENT_STATION_USERS);
			Boolean subUsers = currentUser.isPermitted(PermissionsConstants.PERMISSION_USER_MANAGEMENT_SUBSTATION_USERS);
			if(allUsers)
				container.addContainerFilter(notRoot);
			else if(stUsers)
				container.addContainerFilter(new And(sid, notRoot));
			else if(subUsers)
				container.addContainerFilter(new And(subid, notRoot));
			else
				container.addContainerFilter(new And(new Equal("employee.station.stationId", 0), notRoot));
		} else if(entityClass == EmployeeType.class){
			container.addContainerFilter(new Not(new Equal("employeeTypeId", 99)));
		}
		table = new Table(null, container);
	}

	protected JPAContainer<T> getContainer() {
		return container;
	}

	@Override
	public void valueChange(ValueChangeEvent event) {
		Object itemId = event.getProperty().getValue();
		Item item = table.getItem(itemId);
		boolean entitySelected = item != null;
		form.setVisible(false);
		editButton.setEnabled(entitySelected);
	}

	@Override
	public String getCaption() {
		return getEntityClass().getSimpleName();
	}

	private static final ShortcutAction SAVE = new ShortcutAction("Save",
			KeyCode.ENTER, null);
	private static final ShortcutAction SAVE2 = new ShortcutAction("^Save");
	private static final ShortcutAction NEW = new ShortcutAction("^New");
	private static final Action EDIT = new Action("Edit");

	private static final Action[] ACTIONS = new Action[] { NEW, EDIT };
	private static final Action[] SHORTCUT_ACTIONS = new Action[] { SAVE,
			SAVE2, NEW };

	@Override
	public Action[] getActions(Object target, Object sender) {
		if (sender == table) {
			return ACTIONS;
		} else {
			return SHORTCUT_ACTIONS;
		}
	}

	@Override
	public void handleAction(Action action, Object sender, Object target) {
		if (action == NEW) {
			addItem();
		} else if (action == EDIT) {
			editItem(target);
		} else if (action == SAVE || action == SAVE2) {
			if (form.isVisible()) {
				form.commit();
			}
		}

	}

	private void editItem(Object itemId) {
		//container.removeItem(itemId);
		Item item = table.getItem(itemId);
		boolean entitySelected = item != null;
		// modify visibility of form and delete button if an item is selected
		form.setVisible(entitySelected);
		editButton.setEnabled(entitySelected);
		if (entitySelected) {
			setFields();
			// set entity item to form and focus it
			form.setItemDataSource(item,
					formEditPropertyIds != null ? Arrays.asList(formEditPropertyIds)
							: item.getItemPropertyIds());
			form.focus();
			commit.setEnabled(true);
			discard.setEnabled(true);
			Window editWindow = new Window();
	    	editWindow.center();
	    	editWindow.setModal(true);
			VerticalLayout verticalLayout = (VerticalLayout) editWindow.getContent();
			verticalLayout.setMargin(true);
	        verticalLayout.setSpacing(true);
			verticalLayout.setSizeUndefined();
	    	verticalLayout.addComponent(form);
	    	getApplication().getMainWindow().addWindow(editWindow);
		}
	}

	protected void addItem() {
		try {
			T newInstance = newInstance();
			
			BeanItem<T> item = new BeanItem<T>(newInstance);
			setFields();
			form.setVisible(true);
			form.setItemDataSource(item,formAddPropertyIds != null ? Arrays.asList(formAddPropertyIds)
					: item.getItemPropertyIds());
			
			form.focus();
			commit.setEnabled(true);
			discard.setEnabled(true);
			Window editWindow = new Window();
	    	editWindow.center();
	    	editWindow.setModal(true);
			VerticalLayout verticalLayout = (VerticalLayout) editWindow.getContent();
			verticalLayout.setMargin(true);
	        verticalLayout.setSpacing(true);
			verticalLayout.setSizeUndefined();
	    	verticalLayout.addComponent(form);
	    	getApplication().getMainWindow().addWindow(editWindow);
		} catch (InstantiationException e) {
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		}
	}
	
	protected void setPermission(Object itemId) {
		Item item = table.getItem(itemId);
		boolean entitySelected = item != null;
		if (entitySelected) {
			int selectedUserId = (Integer) table.getValue();
			AssignPermissionsWindow assignPermissions = new AssignPermissionsWindow(app, selectedUserId);
	    	getApplication().getMainWindow().addWindow(assignPermissions);
		}
	}
	
	protected void alterRouteDetails(Object itemId) {
		Item item = table.getItem(itemId);
		boolean entitySelected = item != null;
		if (entitySelected) {
			int selectedRouteId = (Integer) table.getValue();
			AlterRouteDetailWindow assignPermissions = new AlterRouteDetailWindow(app, selectedRouteId);
	    	getApplication().getMainWindow().addWindow(assignPermissions);
		}
	}
	
	private void saveUser(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String username = form.getField("username").getValue().toString();
			Query o = em.createQuery("SELECT u FROM User u Where u.username = '" + username +"'");
			int emp = (Integer) form.getField("employee").getValue();
			Query e = em.createQuery("SELECT u FROM User u Where u.employee.employeeId = " + emp);
			User user = new User();
			if(o.getResultList().size() == 0 && e.getResultList().size() == 0){
				user.setUsername(username);
				user.setPassword(form.getField("password").getValue().toString());
				Employee employee = em.find(Employee.class, emp);
				user.setEmployee(employee);
				em.persist(user);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			} else {
				if(e.getResultList().size() != 0)
					app.showNotification("This employee has a user account to access the system");
				else if(o.getResultList().size() != 0)
					app.showNotification("This username already exits please choose another one");
				em.getTransaction().rollback();
				discard.setEnabled(false);
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editUser(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String userId = form.getField("userId").getValue().toString();
			Query o = em.createQuery("SELECT u FROM User u Where u.userId = " + userId);
			if(o.getResultList().size() != 0){
				User u = (User) o.getSingleResult();
				u.setPassword(form.getField("password").getValue().toString());
				em.merge(u);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
			} else {
				app.showNotification("User / employee combination doesn't exists");
				discard.setEnabled(false);
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveEmployeeType(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String description = form.getField("description").getValue().toString();
			EmployeeType employeeType = new EmployeeType();
			employeeType.setDescription(description);
			em.persist(employeeType);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editEmployeeType(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("employeeTypeId").getValue().toString();
			Query o = em.createQuery("SELECT em FROM EmployeeType em Where em.employeeTypeId = " + id);
			if(o.getResultList().size() != 0){
				EmployeeType item = (EmployeeType) o.getSingleResult();
				String description = form.getField("description").getValue().toString();
				item.setDescription(description);
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveEmployeeStatus(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String description = form.getField("description").getValue().toString();
			EmployeeStatus item = new EmployeeStatus();
			item.setDescription(description);
			em.persist(item);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editEmployeeStatus(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("employeeStatusId").getValue().toString();
			Query o = em.createQuery("SELECT es FROM EmployeeStatus es Where es.employeeStatusId = " + id);
			if(o.getResultList().size() != 0){
				EmployeeStatus item = (EmployeeStatus) o.getSingleResult();
				String description = form.getField("description").getValue().toString();
				item.setDescription(description);
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveParcelAction(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String description = form.getField("description").getValue().toString();
			ParcelAction item = new ParcelAction();
			item.setDescription(description);
			em.persist(item);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editParcelAction(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("parcelActionId").getValue().toString();
			Query o = em.createQuery("SELECT pa FROM ParcelAction pa Where pa.parcelActionId = " + id);
			if(o.getResultList().size() != 0){
				ParcelAction item = (ParcelAction) o.getSingleResult();
				String description = form.getField("description").getValue().toString();
				item.setDescription(description);
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveParcelStatus(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String description = form.getField("description").getValue().toString();
			ParcelStatus item = new ParcelStatus();
			item.setDescription(description);
			em.persist(item);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editParcelStatus(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("parcelStatusId").getValue().toString();
			Query o = em.createQuery("SELECT ps FROM ParcelStatus ps Where ps.parcelStatusId = " + id);
			if(o.getResultList().size() != 0){
				ParcelStatus item = (ParcelStatus) o.getSingleResult();
				String description = form.getField("description").getValue().toString();
				item.setDescription(description);
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveParcelType(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String description = form.getField("description").getValue().toString();
			ParcelType item = new ParcelType();
			item.setDescription(description);
			em.persist(item);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editParcelType(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("parcelTypeId").getValue().toString();
			Query o = em.createQuery("SELECT pt FROM ParcelType pt Where pt.parcelTypeId = " + id);
			if(o.getResultList().size() != 0){
				ParcelType item = (ParcelType) o.getSingleResult();
				String description = form.getField("description").getValue().toString();
				item.setDescription(description);
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void savePaymentMode(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String description = form.getField("description").getValue().toString();
			PaymentMode item = new PaymentMode();
			item.setDescription(description);
			em.persist(item);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editPaymentMode(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("paymentModeId").getValue().toString();
			Query o = em.createQuery("SELECT pm FROM PaymentMode pm Where pm.paymentModeId = " + id);
			if(o.getResultList().size() != 0){
				PaymentMode item = (PaymentMode) o.getSingleResult();
				String description = form.getField("description").getValue().toString();
				item.setDescription(description);
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveStationStatus(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String description = form.getField("description").getValue().toString();
			StationStatus item = new StationStatus();
			item.setDescription(description);
			em.persist(item);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editStationStatus(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("id").getValue().toString();
			Query o = em.createQuery("SELECT st FROM StationStatus st Where st.id = " + id);
			if(o.getResultList().size() != 0){
				StationStatus item = (StationStatus) o.getSingleResult();
				String description = form.getField("description").getValue().toString();
				item.setDescription(description);
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveStation(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			Station item = new Station();
			item.setCode(form.getField("code").getValue().toString());
			item.setName(form.getField("name").getValue().toString());
			StationStatus status = em.find(StationStatus.class, form.getField("status").getValue());
			Country country = em.find(Country.class, form.getField("country").getValue());
			item.setStatus(status);
			item.setCountry(country);
			em.persist(item);
			
			em.flush();
			
			Substation sub = loadNewSubstation(item.getCode(), item.getName(), item.getStationId(), status.getId(), em);
			em.persist(sub);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editStation(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("stationId").getValue().toString();
			Query o = em.createQuery("SELECT st FROM Station st Where st.stationId = " + id);
			if(o.getResultList().size() != 0){
				Station item = (Station) o.getSingleResult();
				item.setName(form.getField("name").getValue().toString());
				StationStatus status = null;
				Long selectedStatus = (Long) form.getField("status").getValue();
				if(item.getStatus().getId() != selectedStatus){
					status = em.find(StationStatus.class, selectedStatus);
					item.setStatus(status);
				}
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveSubstation(String code, String name, Integer stationId, Long statusId){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			Substation item = loadNewSubstation(code, name, stationId, statusId, em);
			
			em.persist(item);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private Substation loadNewSubstation(String code, String name, Integer stationId, Long statusId, EntityManager em) {
		Substation item = new Substation();
		
		item.setCode(code);
		item.setName(name);
		Station station = em.find(Station.class, stationId);
		StationStatus status = em.find(StationStatus.class, statusId);
		int maxStationNumber = 0;
		Query q = em.createQuery("SELECT max(ss.substationNumber) FROM Substation ss where ss.station.stationId ="+station.getStationId()); 
		if(q.getResultList().size() != 0 && q.getSingleResult() != null)
				maxStationNumber = (Integer) q.getSingleResult();
		item.setSubstationNumber(maxStationNumber+1);
		item.setStation(station);
		item.setStatus(status);
		
		return item;
	}
	
	private void editSubstation(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("substationId").getValue().toString();
			Query o = em.createQuery("SELECT st FROM Substation st Where st.substationId = " + id);
			if(o.getResultList().size() != 0){
				Substation item = (Substation) o.getSingleResult();
				item.setName(form.getField("name").getValue().toString());
				StationStatus status = null;
				Long selectedStatus = (Long) form.getField("status").getValue();
				if(item.getStatus().getId() != selectedStatus){
					status = em.find(StationStatus.class, selectedStatus);
					item.setStatus(status);
				}
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveEmployee(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			Employee item = new Employee();
			item.setFirstname(form.getField("firstname").getValue().toString());
			item.setLastname(form.getField("lastname").getValue().toString());
			item.setIdNumber(form.getField("idNumber").getValue().toString());
			item.setDrivingLicenceNumber((String) form.getField("drivingLicenceNumber").getValue());
			item.setDrivingLicenceExpireDate((Date) form.getField("drivingLicenceExpireDate").getValue());
			item.setBloodgroup((String) form.getField("bloodgroup").getValue());
			item.setAddress((String) form.getField("address").getValue());
			item.setPostcode((String) form.getField("postcode").getValue());
			item.setCity((String) form.getField("city").getValue());
			item.setTel1(form.getField("tel1").getValue().toString());
			item.setTel2((String) form.getField("tel2").getValue());
			item.setJoinDate(new Date());
			item.setDob((Date) form.getField("dob").getValue());
			item.setTerminatedDate((Date) form.getField("terminatedDate").getValue());
			
			
			Station station = em.find(Station.class, form.getField("station").getValue());
			Substation substation = em.find(Substation.class, form.getField("substation").getValue());
			EmployeeStatus employeeStatus = em.find(EmployeeStatus.class, form.getField("employeeStatus").getValue());
			EmployeeType employeeType = em.find(EmployeeType.class, form.getField("employeeType").getValue());
			Gender gender = em.find(Gender.class, form.getField("gender").getValue());
			
			item.setEmployeeType(employeeType);
			item.setGender(gender);
			item.setSubstation(substation);
			item.setEmployeeStatus(employeeStatus);
			item.setStation(station);
			em.persist(item);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editEmployee(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("employeeId").getValue().toString();
			Query o = em.createQuery("SELECT e FROM Employee e Where e.employeeId = " + id);
			if(o.getResultList().size() != 0){
				Employee item = (Employee) o.getSingleResult();
				item.setFirstname(form.getField("firstname").getValue().toString());
				item.setLastname(form.getField("lastname").getValue().toString());
				item.setIdNumber(form.getField("idNumber").getValue().toString());
				item.setDrivingLicenceNumber((String) form.getField("drivingLicenceNumber").getValue());
				item.setDrivingLicenceExpireDate((Date) form.getField("drivingLicenceExpireDate").getValue());
				item.setBloodgroup((String) form.getField("bloodgroup").getValue());
				item.setAddress((String) form.getField("address").getValue());
				item.setPostcode((String) form.getField("postcode").getValue());
				item.setCity((String) form.getField("city").getValue());
				item.setTel1(form.getField("tel1").getValue().toString());
				item.setTel2((String) form.getField("tel2").getValue());
				item.setJoinDate(new Date());
				item.setDob((Date) form.getField("dob").getValue());
				item.setTerminatedDate((Date) form.getField("terminatedDate").getValue());
				
				Gender gender = null;
				Long genderId = (Long) form.getField("gender").getValue();
				if(item.getGender().getId() != genderId){
					gender = em.find(Gender.class, genderId);
					item.setGender(gender);
				}
				
				EmployeeStatus employeeStatus = null;
				int selectedEmployeeStatus = (Integer) form.getField("employeeStatus").getValue();
				if(item.getEmployeeStatus().getEmployeeStatusId() != selectedEmployeeStatus){
					employeeStatus = em.find(EmployeeStatus.class, selectedEmployeeStatus);
					item.setEmployeeStatus(employeeStatus);
				}
				EmployeeType employeeType = null;
				int selectedEmployeeType = (Integer) form.getField("employeeType").getValue();
				if(item.getEmployeeType().getEmployeeTypeId() != selectedEmployeeType){
					employeeType = em.find(EmployeeType.class, selectedEmployeeType);
					item.setEmployeeType(employeeType);
				}
				Station station = null;
				int selectedStation = (Integer) form.getField("station").getValue();
				if(item.getStation().getStationId() != selectedStation){
					station = em.find(Station.class, selectedStation);
					item.setStation(station);
				}
				Substation substation = null;
				int selectedSubstation = (Integer) form.getField("substation").getValue();
				if(item.getSubstation().getSubstationId() != selectedSubstation){
					substation = em.find(Substation.class, selectedSubstation);
					item.setSubstation(substation);
				}				
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveBus(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			Bus item = new Bus();
			item.setRegistrationNumber(form.getField("registrationNumber").getValue().toString());
			item.setMake((String) form.getField("make").getValue());
			item.setModel((String) form.getField("model").getValue());
			item.setTonnage((String) form.getField("tonnage").getValue());
			String millage = (String) form.getField("millage").getValue();
			item.setMillage(millage != null ? Integer.parseInt(millage): null);
			item.setChasisNumber((String) form.getField("chasisNumber").getValue());
			String nextService = (String) form.getField("nextService").getValue();
			item.setNextService(nextService != null ? Integer.parseInt(nextService) : null);
			String lastfuel = (String) form.getField("lastfuel").getValue();
			item.setLastfuel(lastfuel != null ? Integer.parseInt(lastfuel) : null);
			item.setAvailable((String) form.getField("available").getValue());
			item.setAvailableDate((Date) form.getField("availableDate").getValue());
			item.setConditionDescription((String) form.getField("conditionDescription").getValue());
			item.setConditionDescriptionDate((Date) form.getField("conditionDescriptionDate").getValue());
			
			Station fromStation = null;
			Integer selectedFromStation = (Integer) form.getField("fromStation").getValue();
			if(selectedFromStation != null){
				fromStation = em.find(Station.class, selectedFromStation);
				item.setFromStation(fromStation);
			}
			Station toStation = null;
			Integer selectedToStation = (Integer) form.getField("toStation").getValue();
			if(selectedToStation != null){
				toStation = em.find(Station.class, selectedToStation);
				item.setToStation(toStation);
			}
			
			em.persist(item);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editBus(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("busId").getValue().toString();
			Query o = em.createQuery("SELECT b FROM Bus b Where b.busId = " + id);
			if(o.getResultList().size() != 0){
				Bus item = (Bus) o.getSingleResult();
				item.setRegistrationNumber(form.getField("registrationNumber").getValue().toString());
				item.setMake((String) form.getField("make").getValue());
				item.setModel((String) form.getField("model").getValue());
				item.setTonnage((String) form.getField("tonnage").getValue());
				String millage = (String) form.getField("millage").getValue();
				item.setMillage(millage != null ? Integer.parseInt(millage): null);
				item.setChasisNumber((String) form.getField("chasisNumber").getValue());
				String nextService = (String) form.getField("nextService").getValue();
				item.setNextService(nextService != null ? Integer.parseInt(nextService) : null);
				String lastfuel = (String) form.getField("lastfuel").getValue();
				item.setLastfuel(lastfuel != null ? Integer.parseInt(lastfuel) : null);
				item.setAvailable((String) form.getField("available").getValue());
				item.setAvailableDate((Date) form.getField("availableDate").getValue());
				item.setConditionDescription((String) form.getField("conditionDescription").getValue());
				item.setConditionDescriptionDate((Date) form.getField("conditionDescriptionDate").getValue());
				
				Station fromStation = null;
				Integer selectedFromStation = (Integer) form.getField("fromStation").getValue();
				if(selectedFromStation != null && item.getFromStation() != null && item.getFromStation().getStationId() != selectedFromStation){
					fromStation = em.find(Station.class, selectedFromStation);
					item.setFromStation(fromStation);
				}
				Station toStation = null;
				Integer selectedToStation = (Integer) form.getField("toStation").getValue();
				if(selectedToStation != null && item.getToStation() != null && item.getToStation().getStationId() != selectedToStation){
					toStation = em.find(Station.class, selectedToStation);
					item.setToStation(toStation);
				}
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveCurrency(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String description = form.getField("name").getValue().toString();
			Currency item = new Currency();
			item.setName(description);
			em.persist(item);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editCurrency(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("id").getValue().toString();
			Query o = em.createQuery("SELECT c FROM Currency c Where c.id = " + id);
			if(o.getResultList().size() != 0){
				Currency item = (Currency) o.getSingleResult();
				String description = form.getField("name").getValue().toString();
				item.setName(description);
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveCountry(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			Country item = new Country();
			item.setName(form.getField("name").getValue().toString());
			Double vat = Double.parseDouble(form.getField("vat").getValue().toString());
			item.setVat(vat == null ? null : vat);
			Currency currency = em.find(Currency.class, form.getField("currency").getValue());
			item.setCurrancy(currency);
			em.persist(item);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editCountry(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("id").getValue().toString();
			Query o = em.createQuery("SELECT c FROM Country c Where c.id = " + id);
			if(o.getResultList().size() != 0){
				Country item = (Country) o.getSingleResult();
				item.setName(form.getField("name").getValue().toString());
				Double vat = Double.parseDouble(form.getField("vat").getValue().toString());
				item.setVat(vat == null ? null : vat);
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveCustomer(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			Customer item = new Customer();
			item.setFirstname(form.getField("firstname").getValue().toString());
			item.setLastname(form.getField("lastname").getValue().toString());
			item.setIdNumber(form.getField("idNumber").getValue().toString());
			item.setAddress((String) form.getField("address").getValue());
			item.setPostcode((String) form.getField("postcode").getValue());
			item.setCity((String) form.getField("city").getValue());
			item.setTel1(form.getField("tel1").getValue().toString());
			item.setTel2((String) form.getField("tel2").getValue());
			
			em.persist(item);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editCustomer(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("customerId").getValue().toString();
			Query o = em.createQuery("SELECT c FROM Customer c Where c.customerId = " + id);
			if(o.getResultList().size() != 0){
				Customer item = (Customer) o.getSingleResult();
				item.setFirstname(form.getField("firstname").getValue().toString());
				item.setLastname(form.getField("lastname").getValue().toString());
				item.setIdNumber(form.getField("idNumber").getValue().toString());
				item.setAddress((String) form.getField("address").getValue());
				item.setPostcode((String) form.getField("postcode").getValue());
				item.setCity((String) form.getField("city").getValue());
				item.setTel1(form.getField("tel1").getValue().toString());
				item.setTel2((String) form.getField("tel2").getValue());
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveAccount(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			Account item = new Account();
			item.setOpeningBalance(new BigDecimal((form.getField("openingBalance").getValue().toString())));
			item.setName(form.getField("name").getValue().toString());
			Customer customer = em.find(Customer.class, form.getField("customer").getValue());
			AccountStatus accountStatus = em.find(AccountStatus.class, form.getField("accountStatus").getValue());
			item.setCustomer(customer);
			item.setAccountStatus(accountStatus);
			em.persist(item);
			
			em.getTransaction().commit();
			app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			commit.setEnabled(false);
			discard.setEnabled(false);
			container.refresh();
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void editAccount(){
		EntityManager em = app.em;
		try{
			em.getTransaction().begin();
			
			String id = form.getField("id").getValue().toString();
			Query o = em.createQuery("SELECT a FROM Account a Where a.id = " + id);
			if(o.getResultList().size() != 0){
				Account item = (Account) o.getSingleResult();
				item.setName(form.getField("name").getValue().toString());
				AccountStatus status = null;
				int selectedStatus = (Integer) form.getField("accountStatus").getValue();
				if(item.getAccountStatus().getId() != selectedStatus){
					status = em.find(AccountStatus.class, selectedStatus);
					item.setAccountStatus(status);
				}
				em.merge(item);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
			e.printStackTrace();
		}
	}
	
	private void saveRoute(){
		EntityManager em = app.em;
		int selectedRouteStart = (Integer) form.getField("routeStart").getValue();
		int selectedRouteEnd = (Integer) form.getField("routeEnd").getValue();
		if(selectedRouteStart != selectedRouteEnd) {
			try{
				em.getTransaction().begin();
				
				Route item = new Route();
				item.setDateCreated(new Date());
				
				Substation routeStart = em.find(Substation.class, selectedRouteStart);
				Substation routeEnd = em.find(Substation.class, selectedRouteEnd);
				RouteStatus routeStatus = em.find(RouteStatus.class, form.getField("routeStatus").getValue());
				
				item.setRouteStart(routeStart);
				item.setRouteEnd(routeEnd);
				item.setRouteStatus(routeStatus);
				em.persist(item);
				
				RouteDetail startRoute = new RouteDetail();
				startRoute.setRoute(item);
				startRoute.setSubstation(routeStart);
				startRoute.setIsStartEnd(true);
				em.persist(startRoute);
				
				RouteDetail endRoute = new RouteDetail();
				endRoute.setRoute(item);
				endRoute.setSubstation(routeEnd);
				endRoute.setIsStartEnd(true);
				em.persist(endRoute);
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
				commit.setEnabled(false);
				discard.setEnabled(false);
				container.refresh();
			} catch (Exception e) {
				app.showNotification("Oooopss something whent wrong !!..");
				em.getTransaction().rollback();
				e.printStackTrace();
			}
		}else {
			app.showNotification("Route start and route end should not be the same substation.");
		}
	}
	
	private void editRoute(){
		EntityManager em = app.em;
		int selectedRouteStart = (Integer) form.getField("routeStart").getValue();
		int selectedRouteEnd = (Integer) form.getField("routeEnd").getValue();
		if(selectedRouteStart != selectedRouteEnd) {
			try{
				em.getTransaction().begin();
				
				String id = form.getField("id").getValue().toString();
				Query o = em.createQuery("SELECT r FROM Route r Where r.id = " + id);
				if(o.getResultList().size() != 0){
					Route item = (Route) o.getSingleResult();
					
					RouteStatus routeStatus = null;
					Long selectedRouteStatus = (Long) form.getField("routeStatus").getValue();
					if(item.getRouteStatus().getId() != selectedRouteStatus){
						routeStatus = em.find(RouteStatus.class, selectedRouteStatus);
						item.setRouteStatus(routeStatus);
					}
					Substation routeStart = null;
					if(item.getRouteStart().getSubstationId() != selectedRouteStart){
						routeStart = em.find(Substation.class, selectedRouteStart);
						
						RouteDetail routeDetailStart = em.createQuery("SELECT rd FROM RouteDetail rd Where rd.route.id = "+ item.getId() + " AND rd.substation.substationId = " + item.getRouteStart().getSubstationId(), RouteDetail.class).getSingleResult();
						
						RouteDetail routeDetail = null;
						try {
							routeDetail = em.createQuery("SELECT rd FROM RouteDetail rd Where rd.route.id = "+ item.getId() + " AND rd.substation.substationId = " + selectedRouteStart, RouteDetail.class).getSingleResult();
							
						} catch (NoResultException e) { }
						
						if(routeDetail != null) {
							routeDetail.setSubstation(item.getRouteStart());
							em.merge(routeDetail);
						}
						
						routeDetailStart.setSubstation(routeStart);
						em.merge(routeDetailStart);
						
						item.setRouteStart(routeStart);
					}
					Substation routeEnd = null;
					if(item.getRouteEnd().getSubstationId() != selectedRouteEnd){
						routeEnd = em.find(Substation.class, selectedRouteEnd);
						
						
						RouteDetail routeDetailEnd = em.createQuery("SELECT rd FROM RouteDetail rd Where rd.route.id = "+ item.getId() + " AND rd.substation.substationId = " + item.getRouteEnd().getSubstationId(), RouteDetail.class).getSingleResult();
						
						RouteDetail routeDetail = null;
						try {
							routeDetail = em.createQuery("SELECT rd FROM RouteDetail rd Where rd.route.id = "+ item.getId() + " AND rd.substation.substationId = " + selectedRouteEnd, RouteDetail.class).getSingleResult();
							
						} catch (NoResultException e) { }
						
						if(routeDetail != null) {
							routeDetail.setSubstation(item.getRouteEnd());
							em.merge(routeDetail);
						}
						
						routeDetailEnd.setSubstation(routeEnd);
						em.merge(routeDetailEnd);
						
						item.setRouteEnd(routeEnd);
					}				
					em.merge(item);
					
					em.getTransaction().commit();
					app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
					commit.setEnabled(false);
					discard.setEnabled(false);
					container.refresh();
				}
			} catch (Exception e) {
				app.showNotification("Oooopss something whent wrong !!..");
				em.getTransaction().rollback();
				e.printStackTrace();
			}
		} else {
			app.showNotification("Route start and route end should not be the same substation.");
		}
	}
	
	private void setFields(){
		if(entityClass == User.class && formType == formTypeCreate){
			UserFieldFactory ff = (UserFieldFactory) fieldFactory;
			ff.userId.setReadOnly(false);
			ff.username.setReadOnly(false);
		} else if(entityClass == User.class && formType == formTypeEdit){
			UserFieldFactory ff = (UserFieldFactory) fieldFactory;
			ff.userId.setReadOnly(true);
			ff.username.setReadOnly(true);
		}
		
		if(entityClass == EmployeeType.class && formType == formTypeCreate){
			EmployeeTypeFieldFactory ff = (EmployeeTypeFieldFactory) fieldFactory;
			ff.employeeTypeId.setReadOnly(false);
		} else if(entityClass == EmployeeType.class && formType == formTypeEdit){
			EmployeeTypeFieldFactory ff = (EmployeeTypeFieldFactory) fieldFactory;
			ff.employeeTypeId.setReadOnly(true);
		}
		
		if(entityClass == EmployeeStatus.class && formType == formTypeCreate){
			EmployeeStatusFieldFactory ff = (EmployeeStatusFieldFactory) fieldFactory;
			ff.employeeStatusId.setReadOnly(false);
		} else if(entityClass == EmployeeStatus.class && formType == formTypeEdit){
			EmployeeStatusFieldFactory ff = (EmployeeStatusFieldFactory) fieldFactory;
			ff.employeeStatusId.setReadOnly(true);
		}
		
		if(entityClass == ParcelAction.class && formType == formTypeCreate){
			ParcelActionFieldFactory ff = (ParcelActionFieldFactory) fieldFactory;
			ff.parcelActionId.setReadOnly(false);
		} else if(entityClass == ParcelAction.class && formType == formTypeEdit){
			ParcelActionFieldFactory ff = (ParcelActionFieldFactory) fieldFactory;
			ff.parcelActionId.setReadOnly(true);
		}
		
		if(entityClass == ParcelStatus.class && formType == formTypeCreate){
			ParcelStatusFieldFactory ff = (ParcelStatusFieldFactory) fieldFactory;
			ff.parcelStatusId.setReadOnly(false);
		} else if(entityClass == ParcelStatus.class && formType == formTypeEdit){
			ParcelStatusFieldFactory ff = (ParcelStatusFieldFactory) fieldFactory;
			ff.parcelStatusId.setReadOnly(true);
		}
		
		if(entityClass == ParcelType.class && formType == formTypeCreate){
			ParcelTypeFieldFactory ff = (ParcelTypeFieldFactory) fieldFactory;
			ff.parcelTypeId.setReadOnly(false);
		} else if(entityClass == ParcelType.class && formType == formTypeEdit){
			ParcelTypeFieldFactory ff = (ParcelTypeFieldFactory) fieldFactory;
			ff.parcelTypeId.setReadOnly(true);
		}
		
		if(entityClass == StationStatus.class && formType == formTypeCreate){
			StationStatusFieldFactory ff = (StationStatusFieldFactory) fieldFactory;
			ff.id.setReadOnly(false);
		} else if(entityClass == StationStatus.class && formType == formTypeEdit){
			StationStatusFieldFactory ff = (StationStatusFieldFactory) fieldFactory;
			ff.id.setReadOnly(true);
		}
		
		if(entityClass == PaymentMode.class && formType == formTypeCreate){
			PaymentModeFieldFactory ff = (PaymentModeFieldFactory) fieldFactory;
			ff.paymentModeId.setReadOnly(false);
		} else if(entityClass == PaymentMode.class && formType == formTypeEdit){
			PaymentModeFieldFactory ff = (PaymentModeFieldFactory) fieldFactory;
			ff.paymentModeId.setReadOnly(true);
		}
		
		if(entityClass == Station.class && formType == formTypeCreate){
			StationFieldFactory ff = (StationFieldFactory) fieldFactory;
			ff.stationId.setReadOnly(false);
		} else if(entityClass == Station.class && formType == formTypeEdit){
			StationFieldFactory ff = (StationFieldFactory) fieldFactory;
			ff.stationId.setReadOnly(true);
		}
		
		if(entityClass == Substation.class && formType == formTypeCreate){
			SubstationFieldFactory ff = (SubstationFieldFactory) fieldFactory;
			ff.substationId.setReadOnly(false);
		} else if(entityClass == Substation.class && formType == formTypeEdit){
			SubstationFieldFactory ff = (SubstationFieldFactory) fieldFactory;
			ff.substationId.setReadOnly(true);
		}
		
		if(entityClass == Employee.class && formType == formTypeCreate){
			EmployeeFieldFactory ff = (EmployeeFieldFactory) fieldFactory;
			ff.employeeId.setReadOnly(false);
		} else if(entityClass == Employee.class && formType == formTypeEdit){
			EmployeeFieldFactory ff = (EmployeeFieldFactory) fieldFactory;
			ff.employeeId.setReadOnly(true);
		}
		
		if(entityClass == Bus.class && formType == formTypeCreate){
			BusFieldFactory ff = (BusFieldFactory) fieldFactory;
			ff.busId.setReadOnly(false);
		} else if(entityClass == Bus.class && formType == formTypeEdit){
			BusFieldFactory ff = (BusFieldFactory) fieldFactory;
			ff.busId.setReadOnly(true);
		}
		
		if(entityClass == Country.class && formType == formTypeCreate){
			CountryFieldFactory ff = (CountryFieldFactory) fieldFactory;
			ff.id.setReadOnly(false);
		} else if(entityClass == Country.class && formType == formTypeEdit){
			CountryFieldFactory ff = (CountryFieldFactory) fieldFactory;
			ff.id.setReadOnly(true);
		}
		
		if(entityClass == Currency.class && formType == formTypeCreate){
			CurrencyFieldFactory ff = (CurrencyFieldFactory) fieldFactory;
			ff.id.setReadOnly(false);
		} else if(entityClass == Currency.class && formType == formTypeEdit){
			CurrencyFieldFactory ff = (CurrencyFieldFactory) fieldFactory;
			ff.id.setReadOnly(true);
		}
		
		if(entityClass == Customer.class && formType == formTypeCreate){
			CustomerFieldFactory ff = (CustomerFieldFactory) fieldFactory;
			ff.customerId.setReadOnly(false);
		} else if(entityClass == Customer.class && formType == formTypeEdit){
			CustomerFieldFactory ff = (CustomerFieldFactory) fieldFactory;
			ff.customerId.setReadOnly(true);
		}
		
		if(entityClass == Account.class && formType == formTypeCreate){
			AccountFieldFactory ff = (AccountFieldFactory) fieldFactory;
			ff.id.setReadOnly(false);
		} else if(entityClass == Account.class && formType == formTypeEdit){
			AccountFieldFactory ff = (AccountFieldFactory) fieldFactory;
			ff.id.setReadOnly(true);
			ff.customer.setReadOnly(true);
		}
		
		if(entityClass == Route.class && formType == formTypeCreate){
			RouteFieldFactory ff = (RouteFieldFactory) fieldFactory;
			ff.id.setReadOnly(false);
		} else if(entityClass == Route.class && formType == formTypeEdit){
			RouteFieldFactory ff = (RouteFieldFactory) fieldFactory;
			ff.id.setReadOnly(true);
		}
	}
	
	public void showPermissionButtion(){
		permissionButton.setVisible(true);
	}
	
	public void showRouteDetailButton(){
		routeDetailButton.setVisible(true);
	}

	/**
	 * This method creates a new instance of the main entity type.
	 * 
	 * @return a new instance of the main entity type
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	protected T newInstance() throws InstantiationException,
			IllegalAccessException {
		T newInstance = getEntityClass().newInstance();
		return newInstance;
	}

	/**
	 * Method to refresh containers in this view. E.g. if a bidirectional
	 * reference is edited from the opposite direction or if we knew that an
	 * other user had edited visible values.
	 */
	public void refreshContainer() {
		container.refresh();
		if (table.getValue() != null) {
			// reset form as e.g. referenced containers may have changed
			form.setItemDataSource(table.getItem(table.getValue()));
		}
	}

	@Override
	public void buttonClick(ClickEvent event) {
		if (event.getButton() == addButton) {
			formType = formTypeCreate;
			addItem();
		} else if (event.getButton() == editButton) {
			formType = formTypeEdit;
			editItem(table.getValue());
		} else if (event.getButton() == permissionButton) {
			setPermission(table.getValue());
		} else if (event.getButton() == routeDetailButton) {
			alterRouteDetails(table.getValue());
		}
	}

	@Override
	public void attach() {
		super.attach();
		panel.focus();
	}
}